// Usage1: ./testdominion <#number of tests>
// Usage2: make testdominion; file testdominion.out is created.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <string.h>
#include "dominion.h"
#include "interface.h"
#include "rngs.h"

FILE *file;

typedef enum { false, true } bool;

int inSupply(struct gameState *game, int card) {
	int cardCount = game->supplyCount[card];
	if (cardCount > 0) {
		return 1;
	}
	return 0;
}

void buyPhase(struct gameState *game, int money) {
	int flip;
	int player = whoseTurn(game);
	if (money >= 8) {
		//victory cards: province
		fprintf(file,"%d: bought Province\n",player);
		buyCard(province, game);
	}
	else if (money >= 6) {
		//action cards: adventurer
		//treasure cards: gold
		flip = floor(Random()*2); // randomly chose: buy gold or adventurer
		fprintf(file,"flip: %d\n", flip);
		if (flip == 0) {
			fprintf(file,"%d: bought Gold\n",player);
			buyCard(gold, game);
		} else if (flip == 1) {
			if (inSupply(game,adventurer)){
				fprintf(file,"%d: bought Adventurer\n",player);
				buyCard(adventurer, game);
			}
		}
	}
	else if (money >= 5) {
		//action cards(5): council room(id:8), mine(id:11), minion(id:17,choice1&2), tribute(id:19), outpost(id:23)
		//victory cards(5): duchy
		flip = floor(Random()*2); // randomly chose: buy victory card or action card
		if (flip == 0) {
			fprintf(file,"%d: bought Duchy\n",player);
			buyCard(duchy, game);
		} else if (flip == 1) {
			int actFive[5] = {council_room,mine,minion,tribute,outpost};
			int cardIdx = floor(Random()*5);
			//randomly choose a card and check if it is purchasable(part of kcard set and in supply)
			if (inSupply(game,actFive[cardIdx])){ //TODO: turn into a while loop and break when all cards have been checked
				char name[MAX_STRING_LENGTH];
				cardNumToName(actFive[cardIdx], name);
				fprintf(file,"%d: bought %s\n",player,name);
				buyCard(actFive[cardIdx], game);
			}
		}
	}
	else if (money >= 4) {
		//action cards(4): feast, garden(not really an action), remodel, smithy, baron, cutpurse, salvager, sea hag, treasure map
		int actFour[9] = {feast,gardens,remodel,smithy,baron,cutpurse,salvager,sea_hag,treasure_map};
		int cardIdx = floor(Random()*9);
		//randomly choose a card and check if it is purchasable(part of kcard set and in supply)
		if (inSupply(game,actFour[cardIdx])){ //TODO: turn into a while loop and break when all cards have been checked
			char name[MAX_STRING_LENGTH];
			cardNumToName(actFour[cardIdx], name);
			fprintf(file,"%d: bought %s\n",player,name);
			buyCard(actFour[cardIdx], game);
		}
	}
	else if (money >= 3) {
		//treasure cards(3): silver
		//action cards(3): village, great hall, steward, ambassador
		flip = floor(Random()*2); // randomly chose: buy treasure card or action card
		if (flip == 0) {
			fprintf(file,"%d: bought Silver\n",player);
			buyCard(silver, game);
		} else if (flip == 1) {
			int actThree[4] = {village,great_hall,steward,ambassador};
			int cardIdx = floor(Random()*4);
			//randomly choose a card and check if it is purchasable(part of kcard set and in supply)
			if (inSupply(game,actThree[cardIdx])){ //TODO: turn into a while loop and break when all cards have been checked
				char name[MAX_STRING_LENGTH];
				cardNumToName(actThree[cardIdx], name);
				fprintf(file,"%d: bought %s\n",player,name);
				buyCard(actThree[cardIdx], game);
			}
		}
	}
	else if (money >= 2) {
		//action cards(2): embargo
		//victory cards(2): estate
		flip = floor(Random()*2); // randomly chose: buy action card or victory card
		if (flip == 0) {
			fprintf(file,"%d: bought Estate\n",player);
			buyCard(estate, game);
		} else if (flip == 1) {
			if (inSupply(game,embargo)){
				fprintf(file,"%d: bought Embargo\n",player);
				buyCard(embargo, game);
			}
		}
	}
	//treasure cards(0): copper
}

void actionPhase(struct gameState *game, int k[10]) {
	//Play first action card in hand
	int choice1 = -1;int choice2=-1;int choice3=-1;int flip;
	int player = whoseTurn(game);
	int handCount = game->handCount[player];
	int handIndex;
	for(handIndex = 0; handIndex < handCount; handIndex++) {
		int card = game->hand[player][handIndex];
		if (card >= adventurer) {
			if (card == feast) {
				bool ok = false;
				while (ok == false) {
					choice1 = floor(Random()*NUM_K_CARDS);
					if (getCardCost(k[choice1])<=5){
						ok = true;
					}
				}
				playCard(handIndex, k[choice1], choice2, choice3, game);
				char name[MAX_STRING_LENGTH];
				char name2[MAX_STRING_LENGTH];
				cardNumToName(card, name);
				cardNumToName(k[choice1], name2);
				fprintf(file,"Player %d plays %s, gains %s\n\n", player, name, name2);
				break;
			}
			else if (card == baron) {
				choice1 = floor(Random()*2);
				playCard(handIndex, choice1, choice2, choice3, game);
				char name[MAX_STRING_LENGTH];
				cardNumToName(card, name);
				fprintf(file,"Player %d plays %s, chose %d\n\n", player, name, choice1);
				break;
			}
			else if (card == minion) {
				flip = floor(Random()*2);
				if (flip == 1){
					choice1 = 1;
					playCard(handIndex, choice1, choice2, choice3, game);
					char name[MAX_STRING_LENGTH];
					cardNumToName(card, name);
					fprintf(file,"Player %d plays %s, chose choice %d\n\n", player, name, 1);
				}
				else if(flip == 0){
					choice2 = 1;
					playCard(handIndex, choice1, choice2, choice3, game);
					char name[MAX_STRING_LENGTH];
					cardNumToName(card, name);
					fprintf(file,"Player %d plays %s, chose choice %d\n\n", player, name, 2);
				}
				break;
			}
			else if (card == steward) {
				flip = floor(Random()*3);
				if (flip == 1) {
					choice1 = 3;
					playCard(handIndex, choice1, choice2, choice3, game);
					char name[MAX_STRING_LENGTH];
					cardNumToName(card, name);
					fprintf(file,"Player %d plays %s, chose choice %d\n\n", player, name, choice1);
				}
				else if(flip == 0) {
					choice1 = 2;
					playCard(handIndex, choice1, choice2, choice3, game);
					char name[MAX_STRING_LENGTH];
					cardNumToName(card, name);
					fprintf(file,"Player %d plays %s, chose choice %d\n\n", player, name, choice1);
				}
				else {
					choice1 = 1;
					playCard(handIndex, choice1, choice2, choice3, game);
					char name[MAX_STRING_LENGTH];
					cardNumToName(card, name);
					fprintf(file,"Player %d plays %s, chose choice %d\n\n", player, name, choice1);
				}
				break;
			}
			else if (card == ambassador) {
				choice2 = floor(Random()*2)+1;
				bool ok = false;
				while (ok == false) {
					choice1 = floor(Random()*handCount);
					if (choice1 != handIndex){
						ok = true;
					}
				}
				playCard(handIndex, choice1, choice2, choice3, game);
				char name[MAX_STRING_LENGTH];
				char name2[MAX_STRING_LENGTH];
				cardNumToName(card, name);
				cardNumToName(handCard(choice1, game), name2);
				fprintf(file,"Player %d plays %s, choice2(return to supply): %d, choice1(card hand index): %d, card name: %s\n\n", player, name, choice2, choice1, name2);
				break;
			}
			else if (card == embargo) {
				bool ok = false;
				while (ok == false) {
					choice1 = floor(Random()*NUM_TOTAL_K_CARDS);
					if (game->supplyCount[choice1]>0){
						ok = true;
					}
				}
				playCard(handIndex, choice1, choice2, choice3, game);
				char name[MAX_STRING_LENGTH];
				char name2[MAX_STRING_LENGTH];
				cardNumToName(card, name);
				cardNumToName(choice1, name2);
				fprintf(file,"Player %d plays %s, choice1: %s\n\n", player, name, name2);
				break;
			}
			else if (card == salvager) {
				bool ok = false;
				while (ok == false) {
					choice1 = floor(Random()*handCount);
					if (choice1 != handIndex){
						ok = true;
					}
				}
				char name[MAX_STRING_LENGTH];
				char name2[MAX_STRING_LENGTH];
				cardNumToName(card, name);
				cardNumToName(handCard(choice1,game), name2);
				playCard(handIndex, choice1, choice2, choice3, game);
				fprintf(file,"Player %d plays %s, trashed: %s\n\n", player, name, name2);
				break;
			}
			else if (card == mine) {
				int x=0;int e;//int cost1,cost2;
				while (x < handCount) {
					choice1 = x;
					e = handCard(choice1,game);
					if (choice1 != handIndex && (e==copper || e==silver || e==gold)){
						x = handCount +10;
					}
					x++;
				}
				//if (x != (handCount+10+1)){
					//break;
				//}
				if (e == gold) {
					choice2 = gold;
				}
				else if (e == silver) {
					choice2 = gold;
				}
				else {
					choice2 = silver;
				}
				char name[MAX_STRING_LENGTH];
				char name2[MAX_STRING_LENGTH];
				char name3[MAX_STRING_LENGTH];
				cardNumToName(card, name);
				cardNumToName(handCard(choice1,game), name2);
				cardNumToName(choice2, name3);
				playCard(handIndex, choice1, choice2, choice3, game);
				fprintf(file,"Player %d plays %s, trashes: %s gains: %s\n\n", player, name, name2, name3);
				break;
			}
			else if (card == remodel) {
				bool ok = false; int cost1, cost2, e;
				while (ok == false) {
					choice1 = floor(Random()*handCount);
					if (choice1 != handIndex){
						ok = true;
					}
				}
				ok = false;
				e = handCard(choice1,game);
				cost1 = getCost(e);
				while (ok == false) {
					choice2 = floor(Random()*NUM_TOTAL_K_CARDS);
					cost2 = getCost(choice2);
					if (game->supplyCount[choice2]>0 && (cost2 <= (cost1+2)) && (choice2>0)){
						ok = true;
					}
				}
				char name[MAX_STRING_LENGTH];
				char name2[MAX_STRING_LENGTH];
				char name3[MAX_STRING_LENGTH];
				cardNumToName(card, name);
				cardNumToName(handCard(choice1,game), name2);
				cardNumToName(choice2, name3);
				playCard(handIndex, choice1, choice2, choice3, game);
				fprintf(file,"Player %d plays %s, trashed: %s, gains: %s\n\n", player, name, name2, name3);
				break;
			}
			else {
				playCard(handIndex, choice1, choice2, choice3, game);
				char name[MAX_STRING_LENGTH];
				cardNumToName(card, name);
				fprintf(file,"Player %d plays %s\n\n", player, name);
				break;
			}
		}
	}
}

int main (int argc, char** argv) {

	//random test seed
	time_t testSeed;
	srand((unsigned) time(&testSeed));
		//srand(1393191888); //to test or regenerate a game with a specific seed, enter seed, unblock this and comment out above
	file = fopen ("gameResults.out", "w");
	int t;
	for (t = 0; t<atoi(argv[1]); t++) {

	int gameSeed,numPlayer,i;
	int k[10] = {0};
	struct gameState g;
	struct gameState * game = &g;

	//random game seed
	gameSeed = rand() % 1000+1;
		//gameSeed = 804;
	//random number of players 2-4
	numPlayer = (rand() % 3)+2;
		//numPlayer = 4;
	//random set of kingdom cards
	selectKingdomCards(gameSeed, k);
	//initialize game
	memset(game,0,sizeof(struct gameState));
	initializeGame(numPlayer, k, gameSeed, game);

	fprintf(file,"Test Seed: %d\n", (int)testSeed);
	fprintf(file,"Game Seed: %d\n", gameSeed);
	fprintf(file,"Number of Players: %d\n", numPlayer);
	fprintf(file,"Kingdom Cards:\n");
	for (i = 0; i < 10; i++) {
		char name[MAX_STRING_LENGTH];
		cardNumToName(k[i], name);
		fprintf(file,"  %-2d %-13s %-2d\n", k[i], name, getCardCost(k[i]));
	}
	fprintf(file,"\n");

	i=0;
	int money = 0;
	int smithyPos = -1;
	int adventurerPos = -1;
	int numSmithies = 0;
	int numAdventurers = 0;
	int turn = 0;
	//Start Game
	while (!isGameOver(game)) {
		money = 0;
		smithyPos = -1;
		adventurerPos = -1;
		//get current players hand stats: money and actions cards
		for (i = 0; i < numHandCards(game); i++) {
			if (handCard(i, game) == smithy)
				smithyPos = i;
			else if (handCard(i, game) == adventurer)
				adventurerPos = i;
		}
		fprintf(file,"Turn: #%d\n",turn);
		money = countHandCoins(whoseTurn(game),game);
		fprintf(file,"Money: %d\n",money);
		//printf("\n");
		//printState(game);
		//printHand(whoseTurn(game), game);
		//printPlayed(whoseTurn(game), game);
		//printDiscard(currentPlayer, game);
		//printDeck(currentPlayer, game);
		if (whoseTurn(game) == 0) {
			//action phase
			actionPhase(game,k);
			//buy phase
			buyPhase(game,money);
			fprintf(file,"0: end turn\n\n");
			endTurn(game);
		}
		else if(whoseTurn(game) == 1){
			//play adventurer card
			if (adventurerPos != -1) {
				fprintf(file,"1: adventurer played from position %d\n", adventurerPos);
				playCard(adventurerPos, -1, -1, -1, game);
				money = 0;
				i=0;
				while(i<numHandCards(game)){
					if (handCard(i, game) == copper){
						playCard(i, -1, -1, -1, game);
						money++;
					}
					else if (handCard(i, game) == silver){
						playCard(i, -1, -1, -1, game);
						money += 2;
					}
					else if (handCard(i, game) == gold){
						playCard(i, -1, -1, -1, game);
						money += 3;
					}
					i++;
				}
			}

			if (money >= 8) {
				fprintf(file,"1: bought province\n");
				buyCard(province, game);
			}
			else if ((money >= 6) && (numAdventurers < 2)) {
				fprintf(file,"1: bought adventurer\n");
				buyCard(adventurer, game);
				numAdventurers++;
			}else if (money >= 6){
				fprintf(file,"1: bought gold\n");
				buyCard(gold, game);
			}
			else if (money >= 3){
				fprintf(file,"1: bought silver\n");
				buyCard(silver, game);
			}
			fprintf(file,"1: end turn\n\n");

			endTurn(game);
		}
		else if(whoseTurn(game) == 2){
			if (adventurerPos != -1) {
				fprintf(file,"2: adventurer played from position %d\n", adventurerPos);
				playCard(adventurerPos, -1, -1, -1, game);
				money = 0;
				i=0;
				while(i<numHandCards(game)){
					if (handCard(i, game) == copper){
						playCard(i, -1, -1, -1, game);
						money++;
					}
					else if (handCard(i, game) == silver){
						playCard(i, -1, -1, -1, game);
						money += 2;
					}
					else if (handCard(i, game) == gold){
						playCard(i, -1, -1, -1, game);
						money += 3;
					}
					i++;
				}
			}

			if (money >= 8) {
				fprintf(file,"2: bought province\n");
				buyCard(province, game);
			}
			else if ((money >= 6) && (numAdventurers < 2)) {
				fprintf(file,"2: bought adventurer\n");
				buyCard(adventurer, game);
				numAdventurers++;
			}else if (money >= 6){
				fprintf(file,"2: bought gold\n");
				buyCard(gold, game);
			}
			else if (money >= 3){
				fprintf(file,"2: bought silver\n");
				buyCard(silver, game);
			}
			fprintf(file,"2: end turn\n\n");

			endTurn(game);
		}
		else {
			if (smithyPos != -1) {
				fprintf(file,"3: smithy played from position %d\n", smithyPos);
				playCard(smithyPos, -1, -1, -1, game);
				fprintf(file,"smithy played.\n");
				money = 0;
				i=0;
				while(i<numHandCards(game)){
					if (handCard(i, game) == copper){
						playCard(i, -1, -1, -1, game);
						money++;
					}
					else if (handCard(i, game) == silver){
						playCard(i, -1, -1, -1, game);
						money += 2;
					}
					else if (handCard(i, game) == gold){
						playCard(i, -1, -1, -1, game);
						money += 3;
					}
					i++;
				}
			}

			if (money >= 8) {
				fprintf(file,"3: bought province\n");
				buyCard(province, game);
			}
			else if (money >= 6) {
				fprintf(file,"3: bought gold\n");
				buyCard(gold, game);
			}
			else if ((money >= 4) && (numSmithies < 2)) {
				fprintf(file,"3: bought smithy\n");
				buyCard(smithy, game);
				numSmithies++;
			}
			else if (money >= 3) {
				fprintf(file,"3: bought silver\n");
				buyCard(silver, game);
			}

			fprintf(file,"3: end turn\n\n");
			endTurn(game);
		}
		turn++;
	} // end of While

	fprintf(file,"Finished game.\n");

	if (numPlayer == 2) {
	fprintf(file,"Player 0: %d\nPlayer 1: %d\n", scoreFor(0, game), scoreFor(1, game));
	} else if (numPlayer == 3) {
	fprintf(file,"Player 0: %d\nPlayer 1: %d\nPlayer 2: %d\n", scoreFor(0, game), scoreFor(1, game),scoreFor(2, game));
	} else {
	fprintf(file,"Player 0: %d\nPlayer 1: %d\nPlayer 2: %d\nPlayer 3: %d\n", scoreFor(0, game), scoreFor(1, game),scoreFor(2, game),scoreFor(3, game));
	}

	}
	return 0;

}
